module task_demo();

/*
Default Port Direction: Any port is seen as input, unless declared as other types.
- input: copy value in at beginning
- output: copy value out at end
- ref: pass reference

Default Data Type: Unless declared, data types of ports are of logic type.

return: A task can be terminated before entask, by usage of return statement.

Variables: Systemverilog allows to have local static, or local dynamic variables.

life time: SystemVerilog allows a task to static or automatic.

wire: Wire data type can not be used in port list.
*/

// 在 module 中, task 默认是 static 的
// 在 static task 中，变量的生命周期是 static 的
// 这意味着变量在 task 的多次调用之间会保持其值

task static static_counter;
    int i;
    i = i + 1;
    $display("static_counter: %0d", i);
endtask

// 在 automatic 任务中，变量的生命周期是 automatic 的,
// 这意味着变量在每次调用任务时都会被重新初始化
task automatic automatic_counter;
    int i;
    i = i + 1;
    $display("automatic_counter: %0d", i);
endtask

// 任务的参数默认方向是 input，与任务是否为 static 或 automatic 无关
task sum(input int x, input int y, output int result);
    result = x + y;
endtask

// ref 传递的是变量的地址（类似指针），而非值拷贝
// 这意味着在任务中对 ref 参数的修改会影响到原始变量
task automatic inc(ref int target, input int amount, int delay = 0);
    #delay target = target + amount;
endtask

// 在 task 中，数组实际上是值传递 (深拷贝)，
// 可以使用 ref 关键字来传递数组的引用
task automatic print_array(ref int arr[]);
    foreach (arr[i]) begin
        $display("arr[%0d]: %0d", i, arr[i]);
    end
endtask

// task 和 function 的区别: task 可以有 delay 和 event control，而 function 不可以
initial begin
    $display("-----------------------------");
    begin
        for (int i = 0; i < 5; i++) begin
            static_counter();
        end
    end
    $display("-----------------------------");
    begin
        for (int i = 0; i < 5; i++) begin
            automatic_counter();
        end
    end
    $display("-----------------------------");
    begin
        int a = 1;
        int b = 2;
        int c;
        sum(a, b, c);
        $display("sum: %0d", c);
    end
    $display("-----------------------------");
    begin
        int a = 10;
        int b = 20;
        $display("@%gns start inc: %0d", $time, a);
        inc(a, b, 3);
        $display("@%gns end inc: %0d", $time, a);
    end
    $display("-----------------------------");
    begin
        int arr[] = '{10, 20, 30, 40, 50};
        print_array(arr);
    end
    $display("-----------------------------");
end

endmodule;
